import time
from datetime import datetime, timedelta

from flask import current_app
from flask import g
from flask import redirect
from flask import render_template, jsonify
from flask import request
from flask import session
from flask import url_for

from info import constants, db
from info import user_login_data
from info.models import User, News, Category
from info.utils import image_storage
from info.utils.response_code import RET
from . import admin_blu

#  增加新闻分类
"""
请求路径: /admin/add_category
请求方式: POST
请求参数: id,name
返回值:errno,errmsg
"""""
@admin_blu.route('/add_category',methods=['POST'])
def add_category():
    #  获取参数
    id=request.json.get('id')
    name=request.json.get('name')
    #  校验参数
    if not name:
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    #  判断是否有分类id,如果有分类，修改分类名称
    if id:
        try:
            category=Category.query.get(id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="查9询数据失败")
        if not category:
            return jsonify(errno=RET.NODATA, errmsg="未查询到分类信息")

        category.name=name
    else:
        #  如果没有分类，就创建分类对象,设置分类属性
        category=Category()
        category.name=name
        try:
            #  提交到数据库中
            db.session.add(category)
            db.session.commit()
        except Exception as e:
            current_app.logger.error(e)
            db.session.rollback()
            return jsonify(errno=RET.NODATA, errmsg="提交失败")

    #  返回响应
    return jsonify(errno=RET.OK, errmsg="保存数据成功")


#  新闻分类管理
"""
请求路径: /admin/news_category
请求方式: GET
请求参数: GET,无
返回值:GET,渲染news_type.html页面, data数据
"""""
@admin_blu.route('/news_type')
def news_category():
    #  查询所有分类数据
    categories=Category.query.all()
    #  将分类对象转换成字典列表
    categories_list=[]
    for category in categories:
        categories_list.append(category.to_dict())
    #  拼接数据并返回

    return render_template('admin/news_type.html',categories_list=categories_list)



#  新闻版式编辑详情
"""
请求路径: /admin/news_edit_detail
请求方式: GET, POST
请求参数: GET, news_id, POST(news_id,title,digest,content,index_image,category_id)
返回值:GET,渲染news_edit_detail.html页面,data字典数据, POST(errno,errmsg)
"""""


@admin_blu.route('/news_edit_detail', methods=['GET', 'POST'])
def news_edit_detail():
    #  第一次请求是get请求
    if request.method == 'GET':
        #  获取参数
        news_id = request.args.get('news_id')
        #  校验参数
        if not news_id:
            return jsonify(errno=RET.PARAMERR, errmsg='该新闻编号不存在')
        # 根据新闻编号查询新闻数据
        try:
            news = News.query.get(news_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DATAERR, errmsg='新闻查询失败')
        if not news: return jsonify(errno=RET.DATAERR, errmsg='新闻不存在')

        #  查询所有分类对象
        try:
            categories=Category.query.all()
            #  弹出最新分类
            categories.pop(0)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DATAERR, errmsg='分类不存在')
        #  将对象列表转成字典列表
        categories_list=[]
        for category in categories:
            categories_list.append(category.to_dict())

        #  返回数据
        return render_template('admin/news_edit_detail.html', news=news.to_dict(),categories_list=categories_list)

    #  post请求可以修改资源
    #  获取参数
    news_id=request.form.get('news_id')
    title=request.form.get('title')
    digest=request.form.get('digest')
    content=request.form.get('content')
    image_data=request.files.get('index_image')
    category_id=request.form.get('category_id')
    #  校验参数
    if not all([news_id,title,digest,content,image_data,category_id]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不全')
    #  根据新闻编号查询新闻对象
    try:
        news=News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='新闻查询失败')
    if not news:
        return jsonify(errno=RET.PARAMERR, errmsg='该新闻不存在')
    #  读取文件，并上传文件
    try:
        image_name=image_storage.image_storage(image_data())
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='七牛云异常')
    news.index_image_url=constants.QINIU_DOMIN_PREFIX+image_name
    #  设置新闻对象
    news.title=title
    news.digest=digest
    news.content=content
    news.category_id=category_id
    #  提交到数据库
    try:
        db.session.add_all(news)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='提交异常')
    #  返回数据
    return jsonify(errno=RET.OK, errmsg='OK')


# 新闻版式编辑
"""
请求路径: /admin/news_edit
请求方式: GET
请求参数: GET, p, keywords
返回值:GET,渲染news_edit.html页面,data字典数据
"""""


@admin_blu.route('/news_edit')
def news_edit():
    #  获取参数
    p = request.args.get('p', 1)
    keywords = request.args.get('keywords')
    #  校验参数
    try:
        p = int(p)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='参数类型转换失败')
    # 分页查询
    try:
        filters = []
        if keywords:
            filters.append(News.title.contains(keywords))
        paginate = News.query.filter(*filters).order_by(News.create_time.desc()).paginate(p, 1, False)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='新闻分页查询失败')
    # 获取分页对象
    totalPage = paginate.pages
    currentPage = paginate.page
    items = paginate.items
    #  将对象列表转换成字典列表
    news_list = []
    for item in items:
        news_list.append(item.to_dict())
    # 拼接数据并返回
    data = {
        'totalPage': totalPage,
        'currentPage': currentPage,
        'news_list': news_list
    }

    return render_template('admin/news_edit.html', data=data)


#  新闻审核详情
"""
请求路径: /admin/news_review_detail
请求方式: GET,POST
请求参数: GET, news_id, POST,news_id, action
返回值:GET,渲染news_review_detail.html页面,data字典数据
"""""


@admin_blu.route('/news_review_detail', methods=['GET', 'POST'])
def news_review_detail():
    #  第一次进来是GET请求
    if request.method == 'GET':
        #  获取参数
        news_id = request.args.get('news_id')
        #  校验参数
        if not news_id: return jsonify(errno=RET.PARAMERR, errmsg='参数不全')
        #  查询新闻对象
        try:
            news = News.query.get(news_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.PARAMERR, errmsg='新闻查询异常')
        # 判断新闻是否存在
        if not news: return jsonify(errno=RET.PARAMERR, errmsg='新闻不存在')
        #  返回页面，携带新闻数据
        return render_template('admin/news_review_detail.html', news=news.to_dict())

    # 获取参数
    news_id = request.json.get('news_id')
    action = request.json.get('action')
    #  校验参数
    if not all(['news_id', 'action']):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不全')

    if action not in ('accept', 'reject'):
        return jsonify(errno=RET.DATAERR, errmsg='没有此行为')
    # 查询新闻是否存在
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg='新闻查询失败')
    if not news: return jsonify(errno=RET.DATAERR, errmsg='新闻不存在')

    #  根据操作类型改变新闻状态
    try:
        if action == 'accept':
            news.status = 0
        else:
            reason = request.json.get('reason')
            if not reason:
                return jsonify(errno=RET.NODATA, errmsg='请填写原因')
            news.status = -1
            news.reason = reason
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg='操作异常')

    # 返回响应
    return jsonify(errno=RET.OK, errmsg='OK')


#  新闻审核
"""
请求路径: /admin/news_review
请求方式: GET
请求参数: GET, p,keyword
返回值:渲染user_list.html页面,data字典数据
"""""


@admin_blu.route('/news_review')
def news_review():
    #  获取参数
    p = request.args.get('p', 1)
    #  搜索关键字
    keyword = request.args.get('keyword')

    #  校验参数
    try:
        p = int(p)
    except Exception as e:
        current_app.logger.error(e)
        p = 1
        return jsonify(errno=RET.DATAERR, errmsg='参数转换失败')

    # 分页查询
    try:

        filters = [News.status != 0]
        #  判断是否有搜索关键字
        if keyword:
            filters.append(News.title.contains(keyword))
        paginate = News.query.filter(*filters).order_by(News.create_time.desc()).paginate(p, 10, False)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg='分页查询失败')

    # 获取分页对象属性
    totalPage = paginate.pages
    currentPage = paginate.page
    items = paginate.items

    #  将对象列表转换成字典列表
    news_list = []
    for item in items:
        news_list.append(item.to_review_dict())

    # 拼接数据并返回
    data = {
        'totalPage': totalPage,
        'currentPage': currentPage,
        'news_list': news_list

    }

    #  返回数据
    return render_template('admin/news_review.html', data=data)


#  用户列表
"""
请求路径: /admin/user_list
请求方式: GET
请求参数: p
返回值:渲染user_list.html页面,data字典数据
"""""


@admin_blu.route('/user_list')
def user_list():
    #  获取参数
    p = request.args.get('p', 1)

    #  校验参数
    try:
        p = int(p)
    except Exception as e:
        current_app.logger.error(e)
        p = 1
        return jsonify(errno=RET.DATAERR, errmsg='参数转换失败')

    # 分页查询
    try:
        paginate = User.query.filter(User.is_admin == False).order_by(User.last_login.desc()).paginate(p, 5, False)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg='分页查询失败')

    # 获取分页对象属性
    totalPage = paginate.pages
    currentPage = paginate.page
    items = paginate.items

    #  将对象列表转换成字典列表
    user_list = []
    for item in items:
        user_list.append(item.to_admin_dict())

    # 拼接数据并返回
    data = {
        'totalPage': totalPage,
        'currentPage': currentPage,
        'user_list': user_list

    }

    #  返回数据
    return render_template('admin/user_list.html', data=data)


#  用户统计
"""
请求路径: /admin/user_count
请求方式: GET
请求参数: 无
返回值:渲染页面user_count.html,字典数据
"""""


@admin_blu.route('/user_count')
def user_count():
    #  查询总人数
    total_count = 0
    try:
        total_count = User.query.filter(User.is_admin == False).count()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg='总人数查询失败')

    # 查询月活人数
    mon_count = 0
    try:
        now = time.localtime()
        #  查询本月1号的字符串
        mon_begin_str = '%d-%02d-01' % (now.tm_year, now.tm_mon)
        #  将本月1号的字符串转成日期对象，两个参数，第一个是字符串，第二个是格式化
        mon_begin_date = datetime.strptime(mon_begin_str, '%Y-%m-%d')
        mon_count = User.query.filter(User.last_login >= mon_begin_date, User.is_admin == False).count()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg='月活人数查询失败')

    # 查询日活人数
    day_count = 0
    try:
        now = time.localtime()
        day_begin_str = '%d-%02d-%02d' % (now.tm_year, now.tm_mon, now.tm_mday)
        day_begin_date = datetime.strptime(day_begin_str, '%Y-%m-%d')
        day_count = User.query.filter(User.is_admin == False, User.last_login >= day_begin_date).count()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg='日活人数查询失败')

    # 活跃日期所对应的活跃人数
    active_date = []  # 活跃的时间段
    active_count = []  # 活跃人数
    for i in range(0, 31):
        #  当天开始时间A
        begin_date = day_begin_date - timedelta(days=i)
        #  当天开始时间的后一天B
        end_date = day_begin_date - timedelta(days=i - 1)
        #  添加当天开始时间字符串到活跃日期中
        active_date.append(begin_date.strftime('%Y-%m-%d'))
        #  查询时间A到B这一天的注册人数
        everyday_active_count = User.query.filter(User.is_admin == False, User.last_login >= begin_date,
                                                  User.last_login <= end_date).count()
        #  添加当天注册人数到获取数量中
        active_count.append(everyday_active_count)

    # 反转
    active_date.reverse()
    active_count.reverse()

    #  拼接数据返回
    data = {
        'total_count': total_count,
        'mon_count': mon_count,
        'day_count': day_count,
        'active_date': active_date,
        'active_count': active_count

    }

    return render_template('admin/user_count.html', data=data)


#  用户首页
@admin_blu.route('/index')
@user_login_data
def index():
    data = {
        'user_info': g.user.to_dict() if g.user else ''
    }

    return render_template('admin/index.html', data=data)


#  用户登陆
@admin_blu.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        #  判断是否有session，有的话直接跳转到首页
        if session.get('is_admin'):
            return redirect(url_for('admin.index'))

        return render_template('admin/login.html')

    # 获取参数
    username = request.form.get('username')
    password = request.form.get('password')

    #  校验参数
    if not all([username, password]):
        return render_template('admin/login.html', errmsg='参数不全')
        # return jsonify(errno=RET.PARAMERR, errmsg='参数不全')

    #  通过用户名查询到管理员对象
    try:
        admin = User.query.filter(User.mobile == username, User.is_admin == True).first()
    except Exception as e:
        current_app.logger.error(e)
        return render_template('admin/login.html', errmsg='查询失败')
        # return jsonify(errno=RET.DBERR, errmsg='查询失败')
    #  判断管理员是否存在
    if not admin:
        return render_template('admin/login.html', errmsg='管理员不存在')
        # return jsonify(errno=RET.DBERR, errmsg='管理员不存在')
    #  判断密码是否正确
    if not admin.check_passowrd(password):
        return render_template('admin/login.html', errmsg='密码不正确')
        # return jsonify(errno=RET.DBERR, errmsg='密码不正确')

    #  保存到session中
    session['nick_name'] = admin.nick_name
    session['admin_id'] = admin.id
    session['mobile'] = admin.mobile
    session['is_admin'] = True
    #  有蓝图装饰，所以要加上蓝图名字
    return redirect(url_for('admin.index'))
